﻿using System.Runtime.InteropServices;

namespace Ast.Core.Pe.Definitions
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct OptionalHeader32 : IOptionalHeader
    {
        public static readonly int StructSize = 0xE0;

        public ushort _magic;

        public SmallVersion _linkerVersion;

        public uint _sizeOfCode;

        public uint _sizeOfInitializedData;

        public uint _sizeOfUninitializedData;

        public uint _addressOfEntryPoint;

        public uint _baseOfCode;

        public uint _baseOfData; // 32 bit only

        public uint _imageBase;

        public uint _sectionAlignment;

        public uint _fileAlignment;

        public Version _operatingSystemVersion;

        public Version _imageVersion;

        public Version _subsystemVersion;

        public uint _win32VersionValue;

        public uint _sizeOfImage;

        public uint _sizeOfHeaders;

        public uint _checkSum;

        public Subsystem _subsystem;

        public DllCharacteristics _dllCharacteristics;

        public uint _sizeOfStackReserve;

        public uint _sizeOfStackCommit;

        public uint _sizeOfHeapReserve;

        public uint _sizeOfHeapCommit;

        public uint _loaderFlags;

        public uint _numberOfRvaAndSizes;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public DataDirectoryEntry[] _dataDirectory;

        public ushort Magic
        {
            get { return _magic; }
        }

        public SmallVersion LinkerVersion
        {
            get { return _linkerVersion; }
        }

        public uint SizeOfCode
        {
            get { return _sizeOfCode; }
        }

        public uint SizeOfInitializedData
        {
            get { return _sizeOfInitializedData; }
        }

        public uint SizeOfUninitializedData
        {
            get { return _sizeOfUninitializedData; }
        }

        public uint AddressOfEntryPoint
        {
            get { return _addressOfEntryPoint; }
        }

        public uint BaseOfCode
        {
            get { return _baseOfCode; }
        }

        public long ImageBase
        {
            get { return _imageBase; }
        }

        public uint SectionAlignment
        {
            get { return _sectionAlignment; }
        }

        public uint FileAlignment
        {
            get { return _fileAlignment; }
        }

        public Version OperatingSystemVersion
        {
            get { return _operatingSystemVersion; }
        }

        public Version ImageVersion
        {
            get { return _imageVersion; }
        }

        public Version SubsystemVersion
        {
            get { return _subsystemVersion; }
        }

        public uint Win32VersionValue
        {
            get { return _win32VersionValue; }
        }

        public uint SizeOfImage
        {
            get { return _sizeOfImage; }
        }

        public uint SizeOfHeaders
        {
            get { return _sizeOfHeaders; }
        }

        public uint CheckSum
        {
            get { return _checkSum; }
        }

        public Subsystem Subsystem
        {
            get { return _subsystem; }
        }

        public DllCharacteristics DllCharacteristics
        {
            get { return _dllCharacteristics; }
        }

        public long SizeOfStackReserve
        {
            get { return _sizeOfStackReserve; }
        }

        public long SizeOfStackCommit
        {
            get { return _sizeOfStackCommit; }
        }

        public long SizeOfHeapReserve
        {
            get { return _sizeOfHeapReserve; }
        }

        public long SizeOfHeapCommit
        {
            get { return _sizeOfHeapCommit; }
        }

        public uint LoaderFlags
        {
            get { return _loaderFlags; }
        }

        public uint NumberOfRvaAndSizes
        {
            get { return _numberOfRvaAndSizes; }
        }

        public DataDirectoryEntry[] DataDirectory
        {
            get { return _dataDirectory; }
        }
    }
}